﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;

namespace ClientAPI
{
    public class NetworkOld
    {
        private Socket commandSocket;
        private Socket chatSocket;
        private Socket fileSocket;

        private Thread commandListener;
        private Thread chatListener;
        private Thread fileListener;

        private int bufferSize;
        private static NetworkOld networkInstance = null;
        private bool commandReceiving = false;
        private bool chatRecieving = false;
        private bool fileReceiving = false;

        //send/recieve file strings
        string _filePath = null;
        string _fileName = null;
        string _folderLocation = null;

        IPAddress[] host = null;

        private NetworkOld()
        {
            bufferSize = 8192;
        }

        public static NetworkOld Instance
        {
            get
            {
                if (networkInstance == null)
                    networkInstance = new NetworkOld();
                return networkInstance;
            }
        }

        public bool IsConnected()
        {
            return commandReceiving;
        }
        
        public void Connect(String ip)
        {
            host = Dns.GetHostAddresses(ip);
            IPEndPoint commandEnd = new IPEndPoint(host[0], 5650);
            
            commandSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            commandSocket.Connect(commandEnd);
            commandReceiving = true;
            

            commandListener = new Thread(new ThreadStart(this.ReceiveCommandMessage));
            commandListener.Name = "CommandListenerTHREAD";            
            commandListener.Start();
        }
        
        public void SendFileConnect()
        {
            IPEndPoint fileEnd = new IPEndPoint(host[0], 5652);
            fileSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            fileSocket.Connect(fileEnd);
            Instance.fileReceiving = true;

            fileListener = new Thread(new ThreadStart(this.SendFile));
            fileListener.Name = "FileTHREAD";
            fileListener.Start();
        }

        public void ReceiveFileConnect(string fileName, string folderLocation)
        {
            Instance._fileName = fileName;
            Instance._folderLocation = folderLocation;
            IPEndPoint fileEnd = new IPEndPoint(host[0], 5652);
            fileSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            fileSocket.Connect(fileEnd);
            Instance.fileReceiving = true;

            fileListener = new Thread(new ThreadStart(this.ReceiveFile));
            fileListener.Name = "FileTHREAD";
            fileListener.Start();
        }

        public void ChatConnect()
        {
            IPEndPoint chatEnd = new IPEndPoint(host[0], 5654);
            chatSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            chatSocket.Connect(chatEnd);
            chatRecieving = true;

            chatListener = new Thread(new ThreadStart(this.ReceiveChatMessage));
            chatListener.Name = "ChatTHREAD";
            chatListener.Start();
        }

        public void Disconnect()
        {
            Protocol.Instance.Disconnect();
            Instance.commandReceiving = false;
            Instance.chatRecieving = false;
            if (fileReceiving) fileSocket.Disconnect(true);
        }

        public void CommandMessage(string message)
        {
            byte[] sendMess = Encoding.UTF8.GetBytes(message);

            System.Diagnostics.Debug.WriteLine("Message sent: " + message);

            commandSocket.Send(sendMess);
        }

        public void FileMessage(string message)
        {
            byte[] sendMess = Encoding.UTF8.GetBytes(message);

            System.Diagnostics.Debug.WriteLine("Message sent: " + message);

            fileSocket.Send(sendMess);
        } 

        public void ChatMessage(string message)
        {
            byte[] sendMess = Encoding.UTF8.GetBytes(message);

            System.Diagnostics.Debug.WriteLine("Message sent: " + message);

            chatSocket.Send(sendMess);
        }              

        public void FileEnd()
        {
            Instance.fileReceiving = false;
        }

        public void FileDisconnect()
        {
            Instance.fileSocket.Shutdown(SocketShutdown.Both);
            Instance.fileSocket.Disconnect(true);
            Instance.fileSocket.Close();
            Instance.fileSocket = null;
        }

        public void SendFile()
        {
            try
            {
                byte[] buffer;
                FileStream neofiledata = new FileStream(_filePath + _fileName, FileMode.Open, FileAccess.Read);

                buffer = new byte[bufferSize];
                int count;

                while ((count = neofiledata.Read(buffer, 0, bufferSize)) > 0)
                {
                    System.Diagnostics.Debug.WriteLine("Bytes Sent: " + fileSocket.Send(buffer, count, SocketFlags.None));
                }
                System.Diagnostics.Debug.WriteLine("file: {0} has been sent", _fileName);
                FileDisconnect();
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine(err);
            }
        }

        private void SendFileDataObject()
        {

        }

        private void ReceiveFileDataObject()
        {
        }

        public void ReceiveFile()
        {
            FileMessage("$FRANK,FILE,DOWNLOAD,"+ _fileName + ",");
            string downloadTo= _folderLocation;
            byte[] buffer = new byte[bufferSize];
            FileStream fileData = new FileStream(downloadTo + "\\" + _fileName, FileMode.Append, FileAccess.Write);
            Thread.Sleep(100);
            int receivedBytesLen = 1;
            //System.Diagnostics.Debug.WriteLine("START DOWNLOAD LOOP");
            do
            {
                receivedBytesLen = fileSocket.Receive(buffer);                
                fileData.Write(buffer, 0, bufferSize);
                
                if (receivedBytesLen == 0)
                {
                    Instance.fileReceiving = false;
                    Thread.Sleep(10);
                }

                FileMessage("$FRANK,FILE,DOWNLOAD,NEXT,");
            }
            while (Instance.fileReceiving);
            System.Diagnostics.Debug.WriteLine("Completed");
            fileData.Flush();
            fileData.Close();
            FileDisconnect();
        }

        private void ReceiveCommandMessage()
        {
            //System.Diagnostics.Debug.WriteLine("Thread entered");
            

            while (Instance.commandReceiving)
            {
                byte[] buffer = new byte[8192];
                commandSocket.Receive(buffer);
                Protocol.Instance.MessageHandler(Encoding.UTF8.GetString(buffer));
                System.Diagnostics.Debug.WriteLine("Message Recived: " + Encoding.UTF8.GetString(buffer));
                //return Encoding.UTF8.GetString(buffer);
            }
            //System.Diagnostics.Debug.WriteLine("Thread exited");

            Instance.commandSocket.Close();
        }

        private void ReceiveChatMessage()
        {
            //System.Diagnostics.Debug.WriteLine("Thread entered");


            while (Instance.chatRecieving)
            {
                byte[] buffer = new byte[8192];
                chatSocket.Receive(buffer);
                Protocol.Instance.MessageHandler(Encoding.UTF8.GetString(buffer));
                System.Diagnostics.Debug.WriteLine("Message Recived: " + Encoding.UTF8.GetString(buffer));
                //return Encoding.UTF8.GetString(buffer);
            }
            //System.Diagnostics.Debug.WriteLine("Thread exited");

            Instance.chatSocket.Close();
        }
    }
}
